前面 26 天,我們把零件一個一個做出來了。接下來三天要把它們組裝成一個真的可以每天用的東西。
今天不寫太多程式碼,先做一件更重要的事:想清楚要做什麼。
這是我做專案時最重要的習慣:在動手之前,先寫下「什麼叫做完成」。
不然很容易陷入「好像還可以再加一個功能」的無限迴圈,最後什麼都做不完。
一個命令列的生活助理,我每天早上打開它,它能告訴我今天該注意什麼;
我可以用自然語言跟它記事情、問天氣;它記得我的習慣。
就這樣。不做網頁介面、不做語音、不接 Google Calendar。
用具體的場景來驗收,而不是模糊的「能用」:
| # | 情境 | 期望行為 |
|---|---|---|
| 1 | 輸入 早安 |
30 秒內產生今日簡報:天氣重點 + 優先待辦 + 一個提醒 |
| 2 | 「明天要不要帶傘?」 | 自動查日期與天氣,用具體數字回答 |
| 3 | 「提醒我禮拜五交報告」 | 正確解析成日期,存進待辦 |
| 4 | 「我有什麼事要做?」 | 列出未完成事項,依優先度排序 |
| 5 | 「我不吃牛肉」 | 記進長期記憶,下次重啟還記得 |
| 6 | 天氣 API 掛掉 | 不崩潰,回覆其他資訊並說明天氣拿不到 |
| 7 | 「把第 3 筆刪掉」 | 先詢問確認,拒絕後不執行且不重試 |
| 8 | 問一個做不到的事 | 誠實說做不到,不編造 |
| 9 | 連續對話 10 輪 | 記得前面說過的內容,成本不失控 |
| 10 | quit 後重新啟動 |
記得長期偏好,對話歷史重新開始 |
**這十條就是 Day 29 要測的東西。**先寫下來,才知道做到哪裡算完。
我把自己實際會用的狀況寫下來:
$ python main.py
> 早安
小幫:早安!今天 10/12 星期日,台北多雲偶陣雨,
下午三點後降雨機率 70%,出門記得帶傘。
氣溫 24-29 度,早晚微涼。
今天最該處理的是「交鐵人賽 Day 27」,今天就到期。
另外「繳停車費」還有兩天,可以一起處理掉。
下午有雨,如果要出門辦事建議排在中午前。
需求:一個指令就能拿到整合過的資訊。
> 提醒我這禮拜要去修機車
小幫:好,記下來了(中優先,期限 10/18)。
需求:自然語言輸入,自動解析時間。
> 明天下午要去信義區,會下雨嗎?
小幫:明天台北下午降雨機率 40%,不算太高但還是有可能,
建議帶把折傘。氣溫 26-30 度,短袖就夠。
需求:AI 自己決定要查什麼。
> 我禮拜三晚上固定有課,那天不要排事情
小幫:了解,我記下來了。之後安排行程時會避開禮拜三晚上。
需求:長期記憶。
把前 26 天的東西畫成一張圖:
┌──────────────┐
│ main.py │ CLI 介面
└──────┬───────┘
│
┌──────▼───────┐
│ Assistant │ 整合層
│ ・組裝 prompt │
│ ・路由 │
└──────┬───────┘
┌───────────────┼───────────────┐
│ │ │
┌──────▼─────┐ ┌──────▼─────┐ ┌──────▼─────┐
│ Memory │ │ Workflow │ │ Agent │
│ ・對話歷史 │ │ ・今日簡報 │ │ ・工具迴圈 │
│ ・使用者檔案│ │ ・新增待辦 │ │ ・預算 │
└────────────┘ └──────┬─────┘ └──────┬─────┘
│ │
┌──────▼───────────────▼─────┐
│ ToolBox │
│ 時間/天氣/待辦/記憶/計算 │
└──────┬──────────────────────┘
│
┌───────────────┼───────────────┐
┌──────▼─────┐ ┌──────▼─────┐ ┌──────▼─────┐
│ 氣象署 API │ │ 本地 JSON │ │ Claude API │
└────────────┘ └────────────┘ └────────────┘
橫切關注點:config / logging / tracer
這是整個設計最關鍵的決定,呼應 Day 23 和 Day 25 的討論:
| 請求類型 | 走哪條路 | 理由 |
|---|---|---|
| 早安 / 今日簡報 | Workflow | 每天都一樣,固定流程最快最便宜 |
| 查天氣 | Workflow | 步驟明確:查 → 分析 → 回答 |
| 看待辦清單 | 純程式 | 連 AI 都不用 |
| 其他任何事 | Agent | 處理長尾情況 |
80% 的常用請求走固定流程,20% 交給 Agent。
life-assistant/
├── .env # API keys(不進 git)
├── .env.example
├── .gitignore
├── requirements.txt
├── README.md
│
├── config.py # 設定管理 (Day 12)
├── logger_setup.py # 日誌 (Day 17)
├── tracer.py # 決策追蹤 (Day 17)
├── prompts.py # Prompt 模板 (Day 19)
├── main.py # CLI 進入點 (Day 29)
├── assistant.py # 整合層 (Day 29)
│
├── agent/
│ ├── __init__.py
│ ├── core.py # Agent 迴圈 (Day 22)
│ ├── budget.py # 預算控制 (Day 25)
│ └── confirm.py # 確認機制 (Day 25)
│
├── tools/
│ ├── __init__.py # 自動註冊 (Day 22)
│ ├── base.py # Tool / ToolBox (Day 15, 22)
│ ├── weather.py # 氣象署 API (Day 14)
│ ├── weather_tool.py
│ ├── datetime_tool.py
│ ├── todo_tool.py
│ ├── memory_tool.py # remember/recall (Day 26)
│ └── calculator_tool.py
│
├── workflows/
│ ├── __init__.py
│ ├── state.py # WorkflowState (Day 24)
│ ├── engine.py # Step / Workflow (Day 24)
│ ├── router.py # 意圖路由 (Day 23)
│ ├── daily_brief.py # 今日簡報 (Day 24)
│ └── add_todo.py # 新增待辦 (Day 23)
│
├── analysis/
│ ├── __init__.py
│ ├── weather_insight.py # 天氣分析 (Day 16)
│ └── todo_insight.py # 待辦分析 (Day 16)
│
├── memory/
│ ├── __init__.py
│ ├── conversation.py # 對話歷史 (Day 26)
│ └── profile.py # 使用者檔案 (Day 26)
│
├── storage/
│ ├── __init__.py
│ └── todo_store.py # 待辦資料存取 (Day 10)
│
├── data/ # 執行時產生(不進 git)
│ ├── todos.json
│ ├── user_profile.json
│ └── cache/
│
├── logs/ # 執行時產生(不進 git)
│ ├── assistant.log
│ └── traces/
│
└── tests/ # Day 29
├── test_tools.py
├── test_workflows.py
└── scenarios.py
這個結構有一條規則:依賴只能往下,不能往上。
main / assistant ← 可以用下面所有的
↓
agent / workflows ← 可以用 tools, analysis, memory, storage
↓
tools ← 可以用 analysis, storage
↓
analysis / storage ← 只能用標準函式庫和 config
↓
config / logger / tracer ← 誰都可以用
如果 storage/todo_store.py 去 import agent/core.py,那就是設計出問題了——會造成循環依賴,而且測試變得很難。
把重要的選擇和理由寫下來。這對三個月後的自己很有幫助。
理由:單一使用者、資料量小(幾百筆)、人可以直接打開看。
代價:不支援多人、沒有交易保證、資料一大就會慢。
什麼時候該換:資料超過幾千筆,或需要多人使用時,換成 SQLite。
理由:30 天的時間有限,CLI 可以專注在 Agent 邏輯本身。
代價:只有我自己會用。
好處:邏輯和介面是分離的——Assistant 類別不知道 CLI 的存在,以後要加網頁或 LINE Bot,只要換掉 main.py。
理由:便宜、快、可預測(Day 23、25 的結論)。
代價:要維護意圖分類器。
驗證方式:Day 29 測試時記錄各路徑的命中率和成本。
理由:透明,使用者隨時可以打開看、自己改、自己刪。
代價:不加密。
界線:所以不記錄任何敏感資訊。這不是技術限制,是設計原則。
理由:Day 25 的結論——不可逆的動作,責任不能外包。
代價:多一步互動。
例外:沒有例外。就算使用者說「不用問我」,我也保留這個機制(最多提供 --yes 參數讓他自己承擔)。
這份清單跟「要做什麼」一樣重要:
| 不做 | 為什麼 |
|---|---|
| 串接 Google Calendar | OAuth 流程會吃掉兩天,而且核心概念已經用天氣 API 示範過了 |
| 語音輸入 | 跟 Agent 主題無關 |
| 多使用者 | 需要帳號系統,超出範圍 |
| 向量資料庫記憶(RAG) | 幾十筆記憶用 JSON 就夠,導入向量庫是過度設計 |
| 網頁介面 | 時間不夠,而且架構已經預留了擴充空間 |
| 自動排程執行 | 可以用系統的排程工具解決,不需要自己做 |
對 30 天的專案來說,會砍需求比會寫程式重要。
我一開始的野心是串行事曆、做網頁、加通知。實際做下來發現,把核心的 Agent 迴圈做穩,比多接三個 API 有價值得多。
哪些地方最可能出問題:
| 風險 | 影響 | 對策 | 對應 |
|---|---|---|---|
| 氣象署 API 掛掉 | 簡報缺資訊 | required=False + 快取 |
Day 24 |
| 模型回傳格式不符 | 程式崩潰 | 結構化輸出 + 防禦性解析 | Day 20 |
| Agent 無限迴圈 | 燒錢 | Budget + 重複偵測 | Day 22, 25 |
| 成本失控 | 帳單爆炸 | 預設走 Workflow + 成本上限 | Day 23, 25 |
| 日期解析錯誤 | 待辦記錯時間 | 強制先查目前時間 | Day 15 |
| 模型假裝完成 | 使用者被誤導 | System prompt 明確禁止 | Day 25 |
| 記憶膨脹 | 每次對話變貴 | max_facts 限制 |
Day 26 |
每一項都在前面的某一天解決過了。這就是為什麼要先打基礎再做專案。
Day 28 的工作清單:
complete_todo、calculate)daily_brief Workflow 補完router.py 的意圖分類與分派Day 29 的工作清單:
assistant.py 整合層main.py CLI 介面明天開始寫程式,把這些零件真的接起來。